18 September, 2016

How to use this slides

The following single character keyboard shortcuts enable alternate display modes:

  • 'f' enable fullscreen mode
  • 'w' toggle widescreen mode
  • 'o' enable overview mode

Download the slides

Here (Right Click > Save As…)

大家的一些課前問題

  • 對於(資料)視覺化想得太簡單或太難
  • 覺得視覺化需要天生的設計美感?
  • 好的視覺化是不是主觀的?
  • 想實做自己的視覺化流程,但不知道如何開展,老是做到一半放棄
  • 用 Excel 辛苦做出的圖表,卻無法在下次重複使用
  • 導入視覺化工具,卻變成「純試試」,一點都不實用,造成導入的軟體無法發揮其效用

為什麼需要視覺化?

關於資料視覺化

  • 發現故事
  • 說服
  • 展示資料
  • 展示資料背後的故事
  • 做決策

EDA Process (Exploratory Data Analysis)

To Communicate

1854 年霍亂

John Snow 繪製了英國倫敦蘇活區的霍亂地圖,比對發現某一水井和感染者的居住地點相近,終於將汙染源鎖定在該水井,一周之後,市政府就封了這口水井,後來也證明霍亂是由汙水傳染而非一般認定的空氣傳染。

我們沒有太多偉大的目標

  • 報告給老闆、同事……
  • 讓相關的人做決策

"The simple graph has brought more information to the data analyst's mind than any other device." – John Tukey

資料視覺化,重點在「資料」

資料視覺化思考範例:Anscombe's Quartet

經典資料集:Anscombe's Quartet

  • 4 x-y datasets
  • 相同的平均數和變異數 ── 從數字上完全看不出差異
  • 用甚麼方式可以看到差異?
#>    vars  n mean   sd median trimmed  mad  min   max range  skew kurtosis
#> x1    1 11  9.0 3.32   9.00    9.00 4.45 4.00 14.00 10.00  0.00    -1.53
#> x2    2 11  9.0 3.32   9.00    9.00 4.45 4.00 14.00 10.00  0.00    -1.53
#> x3    3 11  9.0 3.32   9.00    9.00 4.45 4.00 14.00 10.00  0.00    -1.53
#> x4    4 11  9.0 3.32   8.00    8.00 0.00 8.00 19.00 11.00  2.47     4.52
#> y1    5 11  7.5 2.03   7.58    7.49 1.82 4.26 10.84  6.58 -0.05    -1.20
#> y2    6 11  7.5 2.03   8.14    7.79 1.47 3.10  9.26  6.16 -0.98    -0.51
#> y3    7 11  7.5 2.03   7.11    7.15 1.53 5.39 12.74  7.35  1.38     1.24
#> y4    8 11  7.5 2.03   7.04    7.20 1.90 5.25 12.50  7.25  1.12     0.63
#>      se
#> x1 1.00
#> x2 1.00
#> x3 1.00
#> x4 1.00
#> y1 0.61
#> y2 0.61
#> y3 0.61
#> y4 0.61
x1 x2 x3 x4 y1 y2 y3 y4
10 10 10 8 8.04 9.14 7.46 6.58
8 8 8 8 6.95 8.14 6.77 5.76
13 13 13 8 7.58 8.74 12.74 7.71
9 9 9 8 8.81 8.77 7.11 8.84
11 11 11 8 8.33 9.26 7.81 8.47
14 14 14 8 9.96 8.10 8.84 7.04
6 6 6 8 7.24 6.13 6.08 5.25
4 4 4 19 4.26 3.10 5.39 12.50
12 12 12 8 10.84 9.13 8.15 5.56
7 7 7 8 4.82 7.26 6.42 7.91
5 5 5 8 5.68 4.74 5.73 6.89

資料視覺化思考範例:Anscombe's Quartet

  • 圖表可看到原本看不到的東西

視覺化之所以會讓人覺得很難

Tukey

  • Box Plot

Stephen Few

  • Dashboard

More Infographics and Design

要選擇什麼工具作圖?

要選擇什麼工具作圖

  1. 這張圖多重要?
  2. 可以花多少時間?值得花這麼多時間嗎?
  3. 有必要這要畫嗎?
  4. 這樣畫想要呈現什麼?

圖表也有分好壞

  • 評斷的標準是什麼?
  • 根據不同的理論可以擷取出上百種原則
  • 所以我們要掌握一些心法,讓我們選擇圖表時更簡單、專注

希望上完課後
大家都能把這個能力帶回去

ggplot2 in R 與繪圖心法

ggplot2 簡介

  • ggplot2 是一個很強大的資料探索及視覺化工具, 是許多最有影響力的 R 套件開發者 Hadley Wickham 所開發
  • 所有繪圖函數都有背後的視覺化邏輯(Grammar of Graphics

Grammar of Graphics 的作用就是幫助我們將圖表拆解成個別的元素, 然後將這些元素按照邏輯個別操作,正確簡單地達到圖表的目的

It is far better to learn a language by actually speaking it!

一個例子學會畫圖:mpg 🚗油耗資料

mpg dataset:
Fuel economy data from 1999 and 2008 for 38 popular models of car.

variable detail
manufacturer 車廠
model 型號
displ 引擎排氣量
year 出廠年份
cyl 氣缸數
trans 自/手排
drv f = front-wheel drive, r = rear wheel drive, 4 = 4wd
cty city miles per gallon 城市駕駛油耗
hwy highway miles per gallon 高速公路駕駛油耗
fl 汽油: ethanol E85, diesel, regular, premium, CNG
class 車型

用圖表回答問題

  • 大引擎的車子更耗油嗎?如果是的話,那有多耗油?
  • 引擎大小和油耗效率之間的關係為何?正/負相關?線性/非線性?相關程度?

如果你給你老闆看這種表格

一個例子學會畫圖:mpg

先看兩個變數:

  1. displ - 引擎排氣公升
  2. hwy - (油耗效率,哩/加侖)

Scatterplots

library(ggplot2)
ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy))

從圖表可歸納幾個結論:

  1. 兩變數為高度負相關 ── 大引擎 => 低效率
  2. 有些車是離群值

Exercise: 用 mpg 資料畫不同的圖

看看不同變數之間的相關

  • 畫出 scatterplot: hwy vs cyl
  • 畫出 scatterplot: class vs drv

Answer-1

## hwy vs cyl
ggplot(data = mpg) +
  geom_point(mapping = aes(x = hwy, y = cyl))

Answer-2

## class vs drv
ggplot(data = mpg) +
  geom_point(mapping = aes(x = class, y = drv))

Aesthetic Mapping

Aesthetic Mapping

  • Grammar of Graphics 裡面最重要的概念就是 "Aesthetic Mapping"
  • 在畫圖前我們先來練習用眼睛👀看 aethetics

Exercise: 觀察 Aesthetic Mapping

  • 有哪些變數 variables
  • 分別對應到哪個 aethetic

Aesthetics 基本題 1

  • x = displ
  • y = hwy
  • color = class

Aesthetic Mappings

在 x-y 二維的 Scatterplot 加入第三個 aesthetic

  • 把 class 對應到點的顏色
  • hint: ?geom_point: 查詢支援的 aesthetics

Aesthetic Mappings

  • x = displ
  • y = hwy
  • color = class
ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy, color = class))

Aesthetics 基本題 2

  • x = displ
  • y = hwy
  • alpha (透明度) = class

Exercise

試試在 x-y 二維的 Scatterplot 加入第三個 aesthetic

  • 把 class 對應到點的alpha (透明度)
  • hint: ?geom_point: 查詢支援的 aesthetics

Answer

ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy, alpha = class))

Aesthetics 基本題 3

  • x = displ
  • y = hwy
  • shape = class

Exercise

試試在 x-y 二維的 Scatterplot 加入第三個 aesthetic

  • 把 class 對應到點的形狀

Answer

ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy, shape = class))
#> Warning: The shape palette can deal with a maximum of 6 discrete values
#> because more than 6 becomes difficult to discriminate; you have 7.
#> Consider specifying shapes manually if you must have them.
#> Warning: Removed 62 rows containing missing values (geom_point).
#> Warning: The shape palette can deal with a maximum of 6 discrete values
#> because more than 6 becomes difficult to discriminate; you have 7.
#> Consider specifying shapes manually if you must have them.

Aesthetic Mappings

ggplot(data = <DATA>) + # Data
  geom_<xxx>(
     mapping = aes(<MAPPINGS>), ##  <= Aesthetic mappings
     stat = <STAT>,
     position = <POSITION>
  ) +
  scale_<xxx>() + coord_<xxx>() + facet_<xxx>()
  theme_()
  • aes() 可以放在:
    • ggplot()裡面 – "記憶效果"(成為所有圖層預設)
    • 外面 + aes()"記憶效果"(成為所有圖層預設)
    • geom_<xxx>()裡面 – "記憶效果"(只對該 geom 有效)
  • geom_<xxx>(inherit.aes=FALSE): overrides the default aesthetics.

Static Aesthetic

有時候你可能只想要手動設定某個固定 aesthetic,這裡的設定只為了美觀, 並不會帶出多餘資料訊息。

  • 將 aesthetic 放在 aes() 裡面: map aesthetic 並自動建立 legend
  • 將 aesthetic 放在 aes() 之外: 手動設定某個固定 aesthetic
ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy), color = "blue")

Aesthetics: Perceptual Task

Aesthetics 不只這些

如何查?

  • ?geom_: 各 geom 有不同支援的 aesthetics

Visual Variable Accuracy

HW: 找圖觀察 Aesthetics

  • 上網 The Economist - Graphic detail 找 2 張圖或自己手上有的圖,找出 variable 對應的 aesthetic
  • 找出是否有多餘的對應(一個 variable 對多個 aesthetic)
    • ✘ 切忌畫蛇添足

Junk Colors

如何判斷好的圖表

一開始我們只要著重在圖表的資訊本身:

  1. 增加資訊
  2. 減少雜訊

Data-Ink Mazimazation

  1. 資訊在哪裡?
    • 資料本身相關的
    • 目的相關的
  2. 雜訊在哪裡?
    • 其他一切不相關的都先當作雜訊

消去不需要的元素

(附錄) How Data-Ink Maximazation

  1. 去除不必要的非資料物件
    • 去掉不必要的背景色彩
    • 去掉無意義的色彩變化
    • 淡化圖表格線
    • 去掉一切立體效果
  2. 弱化和統一剩下的非資料物件
    • 使用淡色的:座標軸、格線、表格線、填滿色
  3. 去除多於變數
    • 一個 x-y 方格 最多只留三個變數,一個畫面太多變數會影響資訊吸收
  4. 強調最重要的資料點
    • 標色

中場休息 ♨️

There are two main plotting functions in ggplot2:

  • qplot(): (quick plot) 需要快速畫圖時才使用,用法和 R 的內建繪圖函數 plot() 差不多
  • ggplot(): 推薦的繪圖方法,搭配繪圖步驟的其他函數逐步建構圖層

ggplot2 起手式

ggplot(data = <DATA>) + # Data
  geom_<xxx>(
     mapping = aes(<MAPPINGS>),
     stat = <STAT>,
     position = <POSITION>
  ) + # Layers & Aesthetic mappings
  scale_<xxx>() + coord_<xxx>() + facet_<xxx>() # Position
  theme_()

Data for Plot – ETL

資料和圖表是一體兩面,先有資料才有圖表

mpg 為例

  • mpg 共有 11 個變數 234 筆資料
  • 這裡需要的繪圖變數 (aesthetic mapping)
    • x: displ
    • y: hwy
#> # A tibble: 234 × 11
#>    manufacturer      model displ  year   cyl      trans   drv   cty   hwy
#>           <chr>      <chr> <dbl> <int> <int>      <chr> <chr> <int> <int>
#> 1          audi         a4   1.8  1999     4   auto(l5)     f    18    29
#> 2          audi         a4   1.8  1999     4 manual(m5)     f    21    29
#> 3          audi         a4   2.0  2008     4 manual(m6)     f    20    31
#> 4          audi         a4   2.0  2008     4   auto(av)     f    21    30
#> 5          audi         a4   2.8  1999     6   auto(l5)     f    16    26
#> 6          audi         a4   2.8  1999     6 manual(m5)     f    18    26
#> 7          audi         a4   3.1  2008     6   auto(av)     f    18    27
#> 8          audi a4 quattro   1.8  1999     4 manual(m5)     4    18    26
#> 9          audi a4 quattro   1.8  1999     4   auto(l5)     4    16    25
#> 10         audi a4 quattro   2.0  2008     4 manual(m6)     4    20    28
#> # ... with 224 more rows, and 2 more variables: fl <chr>, class <chr>

Geoms

這兩張圖差在哪裡?

Geoms

  • Geom 決定圖表呈現的「幾何圖形物件」,也就是你眼睛看到的資料呈現方式
  • geom_<xxx>()
ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy))

ggplot(data = mpg) +
  geom_smooth(mapping = aes(x = displ, y = hwy))

Layers 圖層觀念

要呈現多個幾何圖形物件 (Geoms) 時要怎麼做到呢?

  • 一個 geom_<xxx>() 就會在圖上畫一圖層 (Layer)
  • 可一層層疊加上去
  • 每個圖層甚至可以用不同的 data,在畫進階圖表時很常用到
  • 但要注意是否有預設的 aesthetic 不小心 mapping 到該圖層

Layers 圖層觀念

  • 兩層圖層
ggplot(data = mpg) +
  geom_point(mapping = aes(x = displ, y = hwy)) +
  geom_smooth(mapping= aes(x = displ, y = hwy))

Geoms

Geoms

  • 因為 Geoms 真的太多了,通常要用的時候再去查 cheatsheet
  • 如同前面所述,不同 Geoms 有不同支援的 Aesthetics

(附錄) Geoms – Cheatsheet

(附錄) Geoms – Cheatsheet

(附錄) Geoms – Cheatsheet

(附錄) Geoms – Cheatsheet

Bar Charts

  • 各種車型(class)的數量?
  • geom_bar()
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class))

在畫圖之前

你可能要先想到畫出這樣的表格:

class n
2seater 5
compact 47
midsize 41
minivan 11
pickup 33
subcompact 35
suv 62

表格與視覺化的關聯

  • 表格就是一種視覺化的方式,有時候一張好的表格資訊就很清楚
  • 畫圖只是將這些資訊再強調出來

Stats (Geom 的一體兩面)

  • stat_<xxx>()
  • 有些 Geom (例如 scatterplot) 畫的是 raw value (stat_identity)
  • 有些 Geom (例如 barplot)會計算新的 stat (e.g., count) 以供畫圖
  • 使用 geom_<xxx>() 時,要注意預設的 stat 是什麼

每個成功的 Geom 背後都有一個偉大的 Stat

stat = "identity" (不轉換)

Stats?

回頭來看 Aesthetic Mapping

  • x: class
  • y: ?? count 不在原本的 mpg 資料中

到底 count 是怎麼算出來的?

  1. 原本可能在 Excel 算
  2. R 幫你算 dplyr::summarise()
  3. ggplot2 geom_bar 幫你算

=> ?geom_bar 的預設 stat 是 "count"

Stats 是怎麼幫你算出來的

先手動處理 stats 再畫圖

  • Plot bar chart with cut in dataset diamonds

dplyr::summarise() 算出 count 這個變數,再用 ggplot2 畫圖

hint: stat = "identity"

d <- mpg %>% 
  group_by(class) %>% 
  summarise(n = n())
d
#> # A tibble: 7 × 2
#>        class     n
#>        <chr> <int>
#> 1    2seater     5
#> 2    compact    47
#> 3    midsize    41
#> 4    minivan    11
#> 5     pickup    33
#> 6 subcompact    35
#> 7        suv    62

ggplot(data = d) +
  geom_bar(mapping = aes(x = class, y = n),
           stat = "identity")

HW: 有時候遇到複雜的問題就需要手動先算 Stats

  • 畫出各種車型(class)的平均油耗 bar chart

hint:

  • dplyr::group_by()
  • dplyr::summarise(mean(xxx)),
  • geom_bar(stat = "identity")
#> # A tibble: 7 × 2
#>        class mean_hwy
#>        <chr>    <dbl>
#> 1    2seater 24.80000
#> 2    compact 28.29787
#> 3    midsize 27.29268
#> 4    minivan 22.36364
#> 5     pickup 16.87879
#> 6 subcompact 28.14286
#> 7        suv 18.12903

沒有排序的 bar chart 很難看

  • 要怎麼排序?
  • reorder(<要排序的變數>, <參照大小>)
    *只能用在手動算的方式
d <- mpg %>% 
  group_by(class) %>% 
  summarise(n = n())
d
#> # A tibble: 7 × 2
#>        class     n
#>        <chr> <int>
#> 1    2seater     5
#> 2    compact    47
#> 3    midsize    41
#> 4    minivan    11
#> 5     pickup    33
#> 6 subcompact    35
#> 7        suv    62

ggplot(data = d) +
  geom_bar(mapping = aes(x = reorder(class, -n), y = n),
           stat = "identity")

Try Bar Charts

  • 填滿顏色 fill

(錯誤示範:不建議同一變數 mapping 多個 aes)

ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class, fill = class))

Geoms + Stats 實例

  • bar charts, histograms: 計算每一組 bin 裡面的數目.
ggplot(data = mpg, aes(x = class)) +
  geom_bar() +
  geom_text(stat = "count",
            aes(label = ..count.., y =..count..),
            vjust = "bottom")

Geoms + Stats 實例

  • 各種車型的油耗效率
  • boxplots: plot quartiles.
ggplot(data = mpg) +
  geom_boxplot(mapping = aes(x = class, y = hwy))

中場休息 ♨️

從抄別人的圖表學起

  • 判斷圖表好壞之後,我們也要學會做好圖表
  • Google: "圖表名稱 + R"
  • 如果要用得順手,平常就要多看別人畫的好圖,要用時才知道從哪裡找起

Google 是學習畫圖的好朋友

Positions:當圖形在位置打架時要怎麼辦?

  • ?geom_bar
  • 堆疊:position = "stack" (default)
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class, fill = manufacturer),
           position = "stack") +
  ggtitle('Position = "stack"')

Positions

position:

  • "identity" 同一位置(覆蓋住後面圖層)
  • "stack" 堆疊
  • "dodge" 併排
  • "fill" 堆疊並 scale 至 100%
  • "jitter" "抖…" 點會互相閃避

畫出各車廠(manufacturer)在不同車型(class)的數量為何?

Position = "identity"

  • 同一位置(覆蓋住後面圖層)
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class, fill = manufacturer),
           position = "identity", alpha = .4) +
  ggtitle('Position = "identity"')

Position = "dodge"

  • 併排
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class, fill = manufacturer),
           position = "dodge") +
  ggtitle('Position = "dodge"')

Position = "fill"

  • 堆疊並 scale 至 100%
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class, fill = manufacturer),
           position = "fill") +
  ggtitle('Position = "fill"')

Too many variables!!!!

  • 看到剛才的車車油耗🚗,是不是覺得還是很難透過圖表理解資料?
  • 剛才畫的圖因為多了第3個變數,所以更難理解了

Facets: Small-Multiples

  • Facets 是很重要的一個呈現方式,一定要學起來
  • 為什麼要用 Facets?
    1. 當同一個座標平面塞入太多變數,會造成大腦無法負荷
    2. 分拆資訊,讓大腦協助腦補更有效率

"Illustrations of postage-stamp size are indexed by category or a label, sequenced over time like the frames of a movie, or ordered by a quantitative variable not used in the single image itself." – Edward Tufte

Exercise

畫出各車廠(manufacturer)在不同車型(class)的數量為何?

先用表格來思考

  • 你的(視覺化)表格要怎麼畫別人才會清楚
  • 在把表格放到圖表上面

三個變數應該怎麼放:

  • manufacturer
  • class
  • count

1. 老闆會叫你回去重做的表格

但卻是我們在 ggplot2 需要拿來畫圖的表格

#> Source: local data frame [32 x 3]
#> Groups: manufacturer [?]
#> 
#>    manufacturer      class     n
#>           <chr>      <chr> <int>
#> 1          audi    compact    15
#> 2          audi    midsize     3
#> 3     chevrolet    2seater     5
#> 4     chevrolet    midsize     5
#> 5     chevrolet        suv     9
#> 6         dodge    minivan    11
#> 7         dodge     pickup    19
#> 8         dodge        suv     7
#> 9          ford     pickup     7
#> 10         ford subcompact     9
#> 11         ford        suv     9
#> 12        honda subcompact     9
#> 13      hyundai    midsize     7
#> 14      hyundai subcompact     7
#> 15         jeep        suv     8
#> 16   land rover        suv     4
#> 17      lincoln        suv     3
#> 18      mercury        suv     4
#> 19       nissan    compact     2
#> 20       nissan    midsize     7
#> 21       nissan        suv     4
#> 22      pontiac    midsize     5
#> 23       subaru    compact     4
#> 24       subaru subcompact     4
#> 25       subaru        suv     6
#> 26       toyota    compact    12
#> 27       toyota    midsize     7
#> 28       toyota     pickup     7
#> 29       toyota        suv     8
#> 30   volkswagen    compact    14
#> 31   volkswagen    midsize     7
#> 32   volkswagen subcompact     6

2. 直接看就很清楚的表格

  • Pivot 樞紐分析表
manufacturer 2seater compact midsize minivan pickup subcompact suv
audi 0 15 3 0 0 0 0
chevrolet 5 0 5 0 0 0 9
dodge 0 0 0 11 19 0 7
ford 0 0 0 0 7 9 9
honda 0 0 0 0 0 9 0
hyundai 0 0 7 0 0 7 0
jeep 0 0 0 0 0 0 8
land rover 0 0 0 0 0 0 4
lincoln 0 0 0 0 0 0 3
mercury 0 0 0 0 0 0 4
nissan 0 2 7 0 0 0 4
pontiac 0 0 5 0 0 0 0
subaru 0 4 0 0 0 4 6
toyota 0 12 7 0 7 0 8
volkswagen 0 14 7 0 0 6 0

3. 讓視覺化增加資訊的清晰度

Facets

  • facet_wrap()

畫出各車廠(manufacturer)在不同車型(class)的數量 bar chart

  • x: class
  • y: count
  • fill 刪掉多餘的 mapping
  • facet: manufacturer
ggplot(data = mpg) +
  geom_bar(mapping = aes(x = class)) +
  facet_wrap( ~ manufacturer, ncol = 2)

Facets

  • 原則:一個座標平面(方格)最好不要超過三個變數
  • Don't overplotting
  • 拆出類別變數 (nominal) 放在個別的小方格 (facets)

當變數很多時 Faceting 就是你最好的朋友!

HW: Faceting 多變數

畫出各車廠(manufacturer)在不同車型(class)的
平均油耗效率(hwy) bar chart

hint:

  • dplyr::group_by(xxx, xxx)
  • dplyr::summarise(mean_hwy = mean(xxx))
  • geom_bar(stat = "identity")
  • facet_wrap()
#> Source: local data frame [32 x 3]
#> Groups: class [?]
#> 
#>      class manufacturer mean_hwy
#>      <chr>        <chr>    <dbl>
#> 1  2seater    chevrolet 24.80000
#> 2  compact         audi 26.93333
#> 3  compact       nissan 28.00000
#> 4  compact       subaru 26.00000
#> 5  compact       toyota 30.58333
#> 6  compact   volkswagen 28.50000
#> 7  midsize         audi 24.00000
#> 8  midsize    chevrolet 27.60000
#> 9  midsize      hyundai 27.71429
#> 10 midsize       nissan 27.42857
#> # ... with 22 more rows

來談談如何判別一個好的資料視覺化圖表

Junk Charts & Trifecta Checkup

Labels

圖表一定要有標題,別人才知道你要講的故事是什麼

  • ggtitle(), xlab(), ylab()
  • 組合技 – labs(): 各種標註(axis labels, legend titles, plot title/subtitle and below-plot caption)

標題

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point(mapping = aes(color = class)) +
  geom_smooth() + 
  ggtitle("Fuel efficiency vs. Engine size")

標題 + 副標題

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point(mapping = aes(color = class)) +
  geom_smooth() + 
  labs(title = "Fuel efficiency vs. Engine size",
       subtitle = "Dataset: mpg")

標題 + 座標軸

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point(mapping = aes(color = class)) +
  geom_smooth() + 
  ggtitle("Fuel efficiency vs. Engine size") +
  xlab("Engine displacement (L)") +
  ylab("Highway fuel efficiency (mpg)") 

Theme

ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point(mapping = aes(color = class)) +
  geom_smooth() +
  theme_bw()

ggplot2 內建 theme

(附錄) Theme 相關套件

ggplot2 的繪圖流程 (附錄)

ggplot2 的繪圖流程 (附錄)

  1. Data (noun/subject)
  2. Aesthetic mappings (adjectives): x, y, color, size, …
  3. Layers: Geom (verb), Stat (adverb)
  4. Position (preposition): Scales, Coord, Facet
  5. Theme

視覺化流程總結

(非常重要!) (非常重要!) (非常重要!)

從結果(產出)倒回來想

  • Issue: 這張圖表想解決的問題是什麼
  • Geoms: 要畫什麼圖?
    • bar chart, line chart, heat map, …
  • Variables: 需要那些變數?我的資料有這些變數嗎?
    • variables needed from the data
  • Aesthetic Mapping
    • x:
    • y:

HW: 畫自己的圖

  • 找出一張平常會畫的圖表,以及其資料,填入上面格式
  • 試著用 ggplot2 畫出來~
    • 資料匯入
    • 資料前處理
    • 畫圖
    • 匯出成 png

中場休息吃午餐 ♨️

R 的繪圖業障消除

業障 1: 中文字型

Mac

ggplot2:

# 在最後加上
theme(text = element_text(family = "STHeiti"))

# 若有用到 geom_text 則要在裡面加 family = "STHeiti"
geom_text(family = "STHeiti")

輸出:

ggsave(device = "png", type = "cairo")`

Linux

基本上沒問題

Windows

基本上沒問題

業障 2: 如何匯入資料

業障 3: Export Plots 如何匯出圖表

p <- ggplot(data = mpg, mapping = aes(x = displ, y = hwy)) +
  geom_point(mapping = aes(color = class)) +
  geom_smooth() +
  theme_bw()

ggsave(p,
       filename = "my_plot.png",
       device = "png", h = 2, w = 3, type = "cairo")
# system(paste("open my_plot.png"))

Export Plots 匯出圖表

ggplot2 進階操作與延伸應用

Scales

scale_<aes>_<變數屬性>()

  • 有時候自動產生的座標刻度看起來很糟(區間不對、單位不對)
  • 這時需要手動調整座標
    1. 刻度 tick-breaks
    2. 標籤文字 labels
    3. 最大最小值 limits

Scales – 數值型座標

scale_*_continuouts()

  • breaks: 刻度向量。(minor_breaks 副格線)
  • labels:
    • A character vector giving labels (must be same length as breaks)
    • A function that takes the breaks as input and returns labels as output
      scales 套件 (千分位comma(), 錢號dollar(), 單位unit_format, …)
  • limits: c(最小值, 最大值). (Use NA to refer to the existing minimum or maximum.)

library(ggplot2movies) # IMDB data
d <- movies %>% filter(votes > 1000) # 篩選投票數 1,000 以上的電影
m <- ggplot(d, aes(rating, votes)) +
  geom_point(na.rm = TRUE)
m
# Manipulating the default position scales lets you:

#  * change the axis labels
m + scale_y_continuous("number of votes")
#  * 千分逗號
m + scale_y_continuous(labels = scales::comma)
#  * modify the tick-breaks
m + scale_x_continuous(breaks = c(0:10))
#  * manually label the ticks
m + scale_x_continuous(breaks = c(2,5,8), 
                       labels = c("2 (horrible)", "5 (ok)", "8 (awesome)"))
#  * modify the axis limits
m + scale_y_continuous(limits = c(0, 5000)) +
    scale_x_continuous(limits = c(7, 8))

Scales – 日期座標

scale_x_date(date_breaks = <date breaks>, date_labels = "'%y-%m")

  • date_breaks: "2 weeks", "10 years" 等時間間隔
  • date_labels: 時間格式?strptime 可查詢 date_labels的時間格式怎麼寫

Scales – 日期座標

# 美國總統資料
presidential
#> # A tibble: 11 × 4
#>          name      start        end      party
#>         <chr>     <date>     <date>      <chr>
#> 1  Eisenhower 1953-01-20 1961-01-20 Republican
#> 2     Kennedy 1961-01-20 1963-11-22 Democratic
#> 3     Johnson 1963-11-22 1969-01-20 Democratic
#> 4       Nixon 1969-01-20 1974-08-09 Republican
#> 5        Ford 1974-08-09 1977-01-20 Republican
#> 6      Carter 1977-01-20 1981-01-20 Democratic
#> 7      Reagan 1981-01-20 1989-01-20 Republican
#> 8        Bush 1989-01-20 1993-01-20 Republican
#> 9     Clinton 1993-01-20 2001-01-20 Democratic
#> 10       Bush 2001-01-20 2009-01-20 Republican
#> 11      Obama 2009-01-20 2017-01-20 Democratic

presidential %>%
  mutate(id = 33 + row_number()) %>% # id: 屆數
  ggplot(aes(start, id)) +
    geom_point() +
    geom_segment(aes(xend = end, yend = id)) +
    scale_x_date(NULL, breaks = presidential$start, date_labels = "'%y") +
  geom_text(aes(label = name), hjust = 0,  vjust = 0, nudge_y = 0.2)

Scales – 離散型座標 (附錄,很少用到)

scale_*_discrete()

p <- ggplot(diamonds, aes(cut)) + geom_bar()
p + scale_x_discrete("Cut", 
                     labels = c("Fair" = "F",
                                "Good" = "G",
                                "Very Good" = "VG",
                                "Perfect" = "P",
                                "Ideal" = "I"))

# Use limits to adjust the which levels (and in what order)
# are displayed
p + scale_x_discrete(limits=c("Fair","Ideal"))
#> Warning: Removed 30779 rows containing non-finite values (stat_count).

# p + xlim("Fair","Ideal", "Good")  # 也可以直接用座標來調
# p + ylim("I1", "IF")

Preattentive Processing

顏色是很強大的工具

  • 低精準性(較難透過顏色判斷數值)
  • 但是很能吸引注意力

Feature Hierarchy

Scale Color and Fill

離散型資料 vs 連續型資料

Scale Color and Fill – 離散型

Scale Color and Fill – Manual (手動填色)

presidential %>%
  mutate(id = 33 + row_number()) %>%
  ggplot(aes(start, id, colour = party)) +
  geom_point() +
  geom_segment(aes(xend = end, yend = id)) +
  scale_colour_manual(values = c(Republican = "Red", Democratic = "Blue")) +
  scale_x_date(NULL, breaks = presidential$start, date_labels = "'%y") +
  geom_text(aes(label = name), hjust = 0,  vjust = 0, nudge_y = 0.2)

Labeling

Exercise: 在剛才畫的 dot plot 標註各"車型"油耗效率最佳的車

mpg %>%
  group_by(class) %>%
  mutate(rank = row_number(desc(hwy))) %>% 
  arrange(class, rank, hwy) %>% 
  View
## 各"車型"油耗效率最佳的車
best_in_class <- mpg %>%
  group_by(class) %>%
  filter(row_number(desc(hwy)) == 1)

ggplot(mpg, aes(x = displ, y = hwy)) +
  geom_point(aes(colour = class)) +
  geom_text(aes(label = model), data = best_in_class)

Labeling

  • ggrepel - 自動計算標註文字的位置

Sometimes labeling on dots is not an easy work when plottng, especially when you have lots of dots in you plotting area.

  • use geom_text_repel() instead of geom_text()

ggplot to Plotly 簡單製作動態圖表

只需要一行神奇的指令!

library(plotly)
p <- ggplot() + ...
ggplotly(p)

Excercise: 請把下面的圖變成動態圖表

p <- ggplot(mpg) +
  geom_point(aes(x = displ, y = hwy, color = class))

報告製作

RMarkdown

終極應用:一條龍用 R 做報告

RMarkdown

  • Markdown 語法
所有換段都必須空一行!!!
所有換段都必須空一行!!!
所有換段都必須空一行!!!

不想換段但想強制換行在後面用兩個空白__

# 大標
## 中標
### 小標

- Bullet Point
- Bullet Point

1. 有序
2. 有序

[連結](url)
![圖片說明](img)

RMarkdown

視覺化應用

Map 畫地圖

Example: 地圖視覺化 – Leaflet

Data Man【畫地圖時最需要注意的地方:人口密度可能欺騙眼睛】

在畫地圖的時候,最需要記得的一件事是:人口密度高的地方,發生某種事件的次數應該也會高。比方說,我們要畫全台灣的寵物走失地圖,因為台北市人口密度高,因此每單位面積寵物隻數,理當比苗栗縣來得高(先不考慮台北市和苗栗縣民誰比較愛養寵物),因此寵物走失的隻數應該也會比較多。

如果把寵物走失密度化成地圖,就會出現台北市的顏色很深,苗栗顏色較淺的情況。但這並不代表台北市的寵物比較容易走失,只是反映兩地的人口密度不同。不過,較沒經驗的繪圖者和讀者,可能就會從這張地圖得出「台北市寵物比較容易走失」的結論,犯下我們今天分享的漫畫中的人一樣的錯誤。

因此,在繪製密度地圖的時候,一定要先想到:我們利用的數據跟人口密度有無相關性,有的話,要怎麼排除人口密度的影響,才能從地圖中找出數據真正埋藏的故事。

Reference

Resources 視覺化資源整理

Data Cleansing (ETL)

  • dplyr
  • tidyr
  • broom

ggplot2 Cookbook and Documentation

ggplot2 輔助繪圖

ggplot2 延伸套件整理

Cheatsheet

Other Viz Packages

  • sjPlot: 快速繪製統計模型和表格 (html output)
  • sjmisc: Utility and recode functions for R and sjPlot. 處理問卷 variable, label, spss file, …
  • dygraphs: (RStudio) 動態繪製 time-series data
  • leaflet: Leaflet 地圖
  • ggvis: (hadley) 動態圖表,可搭配 Shiny,尚未有完整應用體系
  • rCharts: (停止開發很久) 動態圖表

R Plot Galleries

Other Plot Galleries

視覺化心法

最後

作業

  • 找圖觀察 Aesthetics
  • 先手動處理 stats 再畫圖
  • Faceting 多變數
  • 畫自己的圖

課後問卷